#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdlib.h>

// 这里的计算平方只是假设，可以想象成是一个需要耗时1秒的复杂计算
int calc_sqr(int a)
{
    sleep(1);
    return a * a;
}

//计算的线程函数
/*
void * 是函数的返回类型，表示该函数会返回一个通用指针，这个指针可以指向任意类型的数据。
calc_thread_fun 是函数名，这是线程启动时会执行的函数。
void *arg 是函数的参数，void * 是通用指针类型，意味着可以传入任意类型的指针。这里的 arg 是从 pthread_create 函数传递过来的参数。
 */
void *calc_thread_fun(void *arg)
{
    int num=*(int *)arg;
    int *result=malloc(sizeof(int));
    *result=calc_sqr(num);

    // return result;
    pthread_exit(result);
}

// 对一个数组中的数分别求平方然后再汇总求和
int main(int argc, char const *argv[])
{
    int items[5] = {1, 2, 3, 4, 5};
    int sqrs[5];

    //用于记录计算开始和结束的时间，以便计算总耗时。
    struct timeval start_t, end_t;
    gettimeofday(&start_t, NULL);

    //5个标识
    pthread_t pts[5];
    // 计算items中每个数的平方，并存储到sqrs中
    for (int i = 0; i < 5; i++)
    {
        // sqrs[i] = calc_sqr(items[i]);
        //创建分线程
        //参数1：这是一个指向 pthread_t 类型变量的指针，用于存储新创建线程的标识符。
        //参数2：线程属性，NULL表示使用默认属性。
        //参数3：这是一个函数指针，指向新线程启动时要执行的函数。
        //参数4：这是一个 void * 类型的指针，用于传递给新线程启动函数的参数。
        pthread_create(&pts[i],NULL,calc_thread_fun,&items[i]);

    }

    //等待所有线程执行完毕，将每个线程的返回值保存到sqrs数组中
    for (int i = 0; i < 5; i++)
    {
       // 声明一个 void 类型的指针 result，用于存储子线程的返回值
       void *result;

       // 调用 pthread_join 函数等待第 i 个子线程结束，并将其返回值存储在 result 指针中
       //参数1：这是一个 pthread_t 类型的变量，用于指定要等待的线程的标识符。
       //参数2：这是一个 void ** 类型的指针，用于存储子线程的返回值。
       pthread_join(pts[i], &result);

       // 将 result 指针转换为 int 类型的指针，并将其指向的值存储到 sqrs 数组的第 i 个位置
       sqrs[i] = *(int *)result;

       // 释放由子线程分配的内存，避免内存泄漏
       free(result);
    }
    
    //使用 gettimeofday 函数记录计算开始的时间。
    gettimeofday(&end_t, NULL);
    // 输出计算耗时
    printf("time = %ld秒\n", end_t.tv_sec - start_t.tv_sec);

    // 累加所有的平方值
    int sum = 0;
    for (int i = 0; i < 5; i++)
    {
        sum += sqrs[i];
    }
    printf("sum = %d\n", sum);

    return 0;
}

